package com.feishi.core.util.common.bean;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by caixq on 6/27 027.
 */
public class ByteBufferProxy {
    private static final int BYTE_DEFAULT_SIZE=128;
    private ByteBuffer bf;
    private int currentSize;
    private int step=16;
    private byte[] bs;
    private int length;


    public ByteBufferProxy() {
        this.currentSize=BYTE_DEFAULT_SIZE;
        bf=ByteBuffer.allocate(this.currentSize) ;
        bs=new byte[this.currentSize];
    }
    public ByteBufferProxy(int size) {
        this.currentSize=size>0?size:BYTE_DEFAULT_SIZE;
        initBuffer();
        bs=new byte[this.currentSize];
    }
    public ByteBufferProxy(int size, int step) {
        this.step = step;
        this.currentSize=size>0?size:BYTE_DEFAULT_SIZE;
        initBuffer();
        bs=new byte[this.currentSize];
    }

    private void initBuffer() {
        bf=ByteBuffer.allocate(this.currentSize) ;
    }

    public void get(byte[] bs,int start,int lenth){
        bf.get(bs,start,lenth);
    }
    public void get(byte[] bs){
        bf.get(bs,0,bs.length);
    }
    public byte[] get(){
        byte[] bytes=new byte[bf.position()];

        System.arraycopy(bf.array(), 0, bytes, 0, bytes.length);
        return bytes;
    }
    public byte[] get(int position){
        byte[] bytes=new byte[position];
        System.arraycopy(bf.array(), 0, bytes, 0, position);
        return bytes;
    }
    public byte[] get(int start,int length){
        byte[] bytes=new byte[length];
        System.arraycopy(bf.array(), start, bytes, 0, length);
        return bytes;
    }

    public ByteBuffer getBf() {
        return bf;
    }

    public void setBf(ByteBuffer bf) {
        this.bf = bf;
    }

    public void put(byte[] bs, int start, int lenth){
        if(bf.position()+lenth>this.currentSize){
            this.currentSize+=Math.ceil((bf.position()+lenth-this.currentSize+0.0)/step)*step;
            ByteBuffer bf=this.bf;
            initBuffer();
            this.bf.put(bf.array(),0,bf.position());
            bf.position();
        }

        bf.put(bs,start,lenth);
    }
    public void put(byte[] bs){
        put(bs,0,bs.length);
    }
    public void read(InputStream is) throws IOException {

        length=is.read(bs);
        put(bs,0,length);
        while (is.available()>0){
            length=is.read(bs);
            put(bs,0,length);
        }
    }



    public void clear() {
        bf.clear();
    }

    public void copyToStart(int index) {
        int target=bf.position()-index;
        bf.clear();
        bf.put(bf.array(),index,target);
    }


    public int find(byte[] bytes) {
        byte[] arr = bf.array();
        if(bytes.length>bf.position()){
            return -1;
        }
        boolean fit;
        for (int i=0;i<bf.position()-bytes.length;i++){
            fit=true;
            for (int j = 0; j <bytes.length ; j++) {
                if(arr[i+j]!=bytes[j]){
                    fit=false;
                    break;
                }
            }
            if (fit==true){
                return i;
            }
        }
        return -1;
    }

    public List<Integer> findAll(byte[] bytes) {
        List<Integer> result=new ArrayList<>();
        byte[] arr = bf.array();
        if(bytes.length>bf.position()){
            return result;
        }
        boolean fit;
        for (int i=0;i<=bf.position()-bytes.length;i++){
            fit=true;
            for (int j = 0; j <bytes.length ; j++) {
                if(arr[i+j]!=bytes[j]){
                    fit=false;
                    break;
                }
            }
            if (fit==true){
                result.add(i);
            }
        }
        return result;
    }
}
